#include "CompressFrame.h"

CompressFrame::CompressFrame(wxWindow* parent) :
  wxPanel(parent,wxID_ANY)
{
  dirpImage=new wxDirPickerCtrl(this,(int)CompressFrameID::dirpImage);
  filepTime=new wxFilePickerCtrl(this,(int)CompressFrameID::filepTime,wxEmptyString,wxFileSelectorPromptStr,wxT("TXT file (*.txt)|*.txt"),wxDefaultPosition,wxDefaultSize,wxFLP_OPEN);
  filepAdditional=new wxFilePickerCtrl(this,(int)CompressFrameID::filepAdditional,wxEmptyString,wxFileSelectorPromptStr,wxT("TXT file (*.txt)|*.txt"),wxDefaultPosition,wxDefaultSize,wxFLP_OPEN);
  filepAdditionalTime=new wxFilePickerCtrl(this,(int)CompressFrameID::filepAdditionalTime,wxEmptyString,wxFileSelectorPromptStr,wxT("TXT file (*.txt)|*.txt"),wxDefaultPosition,wxDefaultSize,wxFLP_OPEN); filepOutput=new wxFilePickerCtrl(this,(int)CompressFrameID::filepOutput,wxEmptyString,wxFileSelectorPromptStr,wxT("StrmBMP file (*.StrmBMP)|*.StrmBMP"),wxDefaultPosition,wxDefaultSize,wxFLP_SAVE);
  btnCompress=new wxButton(this,(int)CompressFrameID::btnCompress,wxT("开始压缩"));
  fileMetaData=new wxFilePickerCtrl(this,(int)CompressFrameID::fileMetaData,wxEmptyString,wxFileSelectorPromptStr,wxT("JSON file (*.json)|*.json"),wxDefaultPosition,wxDefaultSize,wxFLP_OPEN);

  wxFlexGridSizer* girdSizer=new wxFlexGridSizer(2,5,5);
  girdSizer->AddGrowableCol(1,1);
  girdSizer->Add(new wxStaticText(this,wxID_ANY,wxT("元数据")));
  girdSizer->Add(fileMetaData,wxSizerFlags(0).Expand());
  girdSizer->Add(new wxStaticText(this,wxID_ANY,wxT("图像目录")));
  girdSizer->Add(dirpImage,wxSizerFlags(0).Expand());
  girdSizer->Add(new wxStaticText(this,wxID_ANY,wxT("时间序列文件")));
  girdSizer->Add(filepTime,wxSizerFlags(0).Expand());
  girdSizer->Add(new wxStaticText(this,wxID_ANY,wxT("附加数据文件")));
  girdSizer->Add(filepAdditional,wxSizerFlags(0).Expand());
  girdSizer->Add(new wxStaticText(this,wxID_ANY,wxT("附加数据的时间文件")));
  girdSizer->Add(filepAdditionalTime,wxSizerFlags(0).Expand());
  girdSizer->Add(new wxStaticText(this,wxID_ANY,wxT("保存路径")));
  girdSizer->Add(filepOutput,wxSizerFlags(0).Expand());

  wxBoxSizer* mainSizer=new wxBoxSizer(wxVERTICAL);
  mainSizer->AddSpacer(5);
  mainSizer->Add(girdSizer,wxSizerFlags(0).Expand());
  mainSizer->AddSpacer(5);
  mainSizer->Add(btnCompress,wxSizerFlags(0).Expand());

  SetSizer(mainSizer);

  Bind(wxEVT_BUTTON,&CompressFrame::on_btnCompress_click,this,(int)CompressFrameID::btnCompress);
}

void CompressFrame::on_btnCompress_click(wxCommandEvent& event)
{
  std::string dirPath=dirpImage->GetPath().utf8_string();
  std::string ImageTimePath=filepTime->GetPath().utf8_string();
  std::string AdditionalPath=filepAdditional->GetPath().utf8_string();
  std::string AdditionalTimePath=filepAdditionalTime->GetPath().utf8_string();
  std::string OutputPath=filepOutput->GetPath().utf8_string();
  std::string MetaFilePath=fileMetaData->GetPath().utf8_string();
  if(MetaFilePath.length()==0 || dirPath.length()==0 || ImageTimePath.length()==0 || AdditionalPath.length()==0 || AdditionalTimePath.length()==0 || OutputPath.length()==0)
  {
    wxMessageBox(wxT("请选择一个路径"),wxT("错误"),wxOK,this);
    return;
  }
  if(
      !std::filesystem::exists(dirPath) ||
      !std::filesystem::exists(ImageTimePath) ||
      !std::filesystem::exists(AdditionalPath) ||
      !std::filesystem::exists(AdditionalTimePath) ||
      !std::filesystem::exists(MetaFilePath)
  )
  {
    wxMessageBox(wxT("无法打开所选的文件路径"),wxT("错误"),wxOK,this);
    return;
  }
  std::ifstream timeFile(ImageTimePath);
  std::ifstream additionalTimeFile(AdditionalTimePath);
  std::ifstream additionalFile(AdditionalPath);
  std::ifstream metaFile(MetaFilePath);
  if(!timeFile.is_open() || !additionalFile.is_open() || !additionalTimeFile.is_open() || !metaFile.is_open())
  {
    wxMessageBox(wxT("无法打开文件"),wxT("错误"),wxOK,this);
    return;
  }

  wxProgressDialog prgDlg(wxT("处理数据"),wxT("扫描文件中"),1,this);
  std::list<std::pair<long,std::filesystem::path>> imgFileList={};
  std::regex reg(R"(([0-9]+)\.bmp)");
  std::smatch match;
  for(std::filesystem::directory_entry i : std::filesystem::directory_iterator(dirPath))
  {
      std::string fileName = i.path().filename().string();
      if(std::regex_match(fileName,match,reg) && match.size()==2)
      {
        int value = std::stoi(match[1].str());
        imgFileList.push_back({value,i.path()});
      }
  }
  if(imgFileList.size()==0)
  {
    wxMessageBox(wxT("没有扫描到bmp文件"),wxT("错误"),wxOK,this);
    return;
  }
  imgFileList.sort(
     [](std::pair<long,std::filesystem::path>& p1,std::pair<long,std::filesystem::path>& p2)
     {return p1.first < p2.first;}
  );
  std::list<uint64_t> imageTimeData={};
  uint64_t imageTime;
  while(timeFile>>imageTime)
  {
    imageTimeData.push_back(imageTime);
  }
  if(imgFileList.size() != imageTimeData.size())
  {
    wxMessageBox(wxT("图像时间和数量不匹配"),wxT("错误"),wxOK,this);
    return;
  }
  std::list<std::pair<uint64_t,int16_t>> additionalList={};
  int16_t additionalValue;
  while(additionalTimeFile>>imageTime && additionalFile>>additionalValue)
  {
    additionalList.push_back({imageTime,additionalValue});
  }
  nlohmann::json MetaData;
  try
  {
    MetaData=nlohmann::json::parse(metaFile);
  }
  catch(std::exception& e)
  {
    wxMessageBox(wxT("无法解析JSON数据,请检查是否有非法字符"),wxT("错误"),wxOK,this);
    return;
  }
  fileHead setFileHead;
  if(MetaData["Version"].is_string())
    SetFileHeadAttributeValue(setFileHead.Version,12,MetaData["Version"]);
  if(MetaData["pixelType"].is_number_integer())
    SetFileHeadAttributeValue<int16_t>(setFileHead.pixelType,MetaData["pixelType"]);
  if(MetaData["SamplingResolution"].is_number_integer())
    SetFileHeadAttributeValue<int16_t>(setFileHead.SamplingResolution,MetaData["SamplingResolution"]);
  if(MetaData["OperatorName"].is_string())
    SetFileHeadAttributeValue(setFileHead.OperatorName,10,MetaData["OperatorName"]);
  if(MetaData["ViewTarget"].is_string())
    SetFileHeadAttributeValue(setFileHead.ViewTarget,10,MetaData["ViewTarget"]);
  if(MetaData["ViewEnvironment"].is_string())
    SetFileHeadAttributeValue(setFileHead.ViewEnvironment,50,MetaData["ViewEnvironment"]);
  if(MetaData["FileName"].is_string())
    SetFileHeadAttributeValue(setFileHead.FileName,50,MetaData["FileName"]);
  if(MetaData["FileCreateTime"].is_number_integer())
    SetFileHeadAttributeValue<int64_t>(setFileHead.FileCreateTime,MetaData["FileCreateTime"]);
  if(MetaData["cameraName"].is_string())
    SetFileHeadAttributeValue(setFileHead.cameraName,10,MetaData["cameraName"]);
  if(MetaData["cameraGain"].is_number_float())
    SetFileHeadAttributeValue<float>(setFileHead.cameraGain,MetaData["cameraGain"]);
  if(MetaData["cameraBlackOffset"].is_number_float())
    SetFileHeadAttributeValue<float>(setFileHead.cameraBlackOffset,MetaData["cameraBlackOffset"]);
  if(MetaData["cameraExpourseTime"].is_number_integer())
    SetFileHeadAttributeValue<int32_t>(setFileHead.cameraExpourseTime,MetaData["cameraExpourseTime"]);
  if(MetaData["imageCollegeInfFrame"].is_number_integer())
    SetFileHeadAttributeValue<int16_t>(setFileHead.imageCollegeInfFrame,MetaData["imageCollegeInfFrame"]);
  if(MetaData["additionalInfCollegeRate"].is_number_integer())
    SetFileHeadAttributeValue<int32_t>(setFileHead.additionalInfCollegeRate,MetaData["additionalInfCollegeRate"]);
  if(MetaData["additionalChannelEnable"].is_boolean())
    SetFileHeadAttributeValue<int8_t>(setFileHead.additionalChannelEnable,bool(MetaData["additionalChannelEnable"])?1:0);
  if(MetaData["additionalChannelName"].is_string())
    SetFileHeadAttributeValue(setFileHead.additionalChannelName,10,MetaData["additionalChannelName"]);
  if(MetaData["additionalChannelUnit"].is_string())
    SetFileHeadAttributeValue(setFileHead.additionalChannelUnit,8,MetaData["additionalChannelUnit"]);
  if(MetaData["additionalDemarcate"].is_number_integer())
    SetFileHeadAttributeValue<int32_t>(setFileHead.additionalDemarcate,MetaData["additionalDemarcate"]);


  prgDlg.SetRange(imgFileList.size());
  try
  {
    StrmBMP_writer writer(OutputPath);
    {
      BMPfile BMP(imgFileList.begin()->second.string());
      ImageInfo imgInfo=BMP.GetImageInfo();
      fileHead* head=writer.getFileHead();
      std::memcpy(head,&setFileHead,sizeof(fileHead));
      writer.BeginInput(imgInfo.width,imgInfo.height,imgInfo.channel);
    }
    auto imageTimePtr=imageTimeData.begin();
    long count=0;
    for(const std::pair<long,std::filesystem::path>& i : imgFileList)
    {
      prgDlg.Update(count++,wxString::Format(L"正在处理第 %ld / %ld 图片",count,(long)imgFileList.size()));
      BMPfile BMP(i.second.string());
      writer.AddImage(BMP.GetImageData(),*imageTimePtr);
      imageTimePtr++;
    }
    count=0;
    for(const auto& i: additionalList)
    {
      prgDlg.Update(count++,wxString::Format(L"正在处理第 %ld / %ld 附加数据",count,(long)additionalList.size()));
      writer.AddAdditional(i.second,i.first);
    }
    writer.EndInput();
  }
  catch (std::exception& e)
  {
    wxMessageBox(wxString::FromUTF8(e.what()),wxT("错误"),wxOK,this);
    return;
  }
}
